package com.adu.music.proxy;

import com.adu.music.bean.Proxy;
import com.adu.music.util.JsoupUtils;
import org.jsoup.Connection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author duchuanchuan
 * @date 2017/1/7
 */
class ProxyChecker {

    private static final Logger logger = LoggerFactory.getLogger(ProxyChecker.class);

    private static final int MAX_CONCURRENT_NUM = 8;
    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private static ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
    private static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

    static boolean available(Proxy proxy) {
        String url = "http://music.163.com/";
        boolean isAvailable = false;
        try {
            Connection.Response resp = JsoupUtils.connectWithBaseHeaders(url)
                    .proxy(proxy.getIp(), proxy.getPort()).execute();
            if (resp.statusCode() == 200) {
                isAvailable = true;
            }
        } catch (IOException e) {
            isAvailable = false;
        }
        return isAvailable;
    }

    static List<Proxy> filterAvailable(List<Proxy> proxyList) {
        logger.info("filtering available proxy ...............");
        final List<Proxy> proxies = new ArrayList<>();
        CountDownLatch latch = new CountDownLatch(MAX_CONCURRENT_NUM);
        AtomicInteger index = new AtomicInteger(0);
        for (int i = 0; i < MAX_CONCURRENT_NUM; i++) {
            new Thread(() -> {
                while (true) {
                    readLock.tryLock();
                    int i1 = index.getAndIncrement();
                    if (i1 >= proxyList.size()) {
                        readLock.unlock();
                        latch.countDown();
                        break;
                    }
                    Proxy proxy = proxyList.get(i1);
                    readLock.unlock();
                    if (available(proxy)) {
                        writeLock.tryLock();
                        proxies.add(proxy);
                        writeLock.unlock();
                    }
                }
            }).start();
        }
        try {
            latch.await();
            logger.info("check proxy ,totaly have {} items are avaliable", proxies.size());
            return proxies;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
